案例名称:百度地图小应用

案例编号:C3

涉及的知识点编号:

涉及的基础实验编号:

作者:

一、项目整体概述

  1. 掌握各类基本控件的使用;

  2. 掌握Activity组件的基本用法;

  3. 进一步熟悉与掌握Fragment使用。

  4. 进一步熟悉适配器、菜单、对话框等相关概念和技术等。

  5. 熟悉百度API地图的。

二、方案设计

本项目主要是模仿美团APP的界面设计。

主要功能:

  1. Baidu API实现的城市选择界面。

2、首页界面

3、订单界面

4、商家界面

三、系统开发步骤

  1. WelComeActivity

app启动后,首先进入WelComeActivity ,在WelComeActivity中申请权限和获取远程数据

1.申请权限

使用百度地图的api来获取当前所在城市,因为需要使用自己的API_KEY,所以大家可能需要自己申请,这网上有很多介绍,这里就不多说了。这里特别要注意的一点是在android 6.0之后部分权限需要动态申请,这里一定要注意。

//判断系统版本,android 6.0之后部分权限需要动态申请
if(Build.VERSION.SDK_INT >= 23){
     PermissionUtil.requestLocatePermission(this);
}

2.获取数据

启动一个AsyncTask,读取sqlite中citys表中数据的版本,正常的逻辑是拿它与服务器中的citys表版本做比较,判断是否需要更新sqlite中的citys表中的数据,这里偷懒,直接默认远程服务器中citys表版本为1,如果sqlite中版本小于1,则通过http协议获取远程服务器中的数据并写入到sqlite中。

CityLocalDao localServices = new CityLocalDao(WelComeActivity.this); 
int versionNum = localServices.getVersionNum();
Log.d(FangConstant.Log_Tag,"versionNum---------"+versionNum);
if(versionNum<1) {
                CityRemoteDao remoteServices = new CityRemoteDao();
                List<City> cityList = remoteServices.queryAllCityList();
                int count = localServices.insertIntoSql(cityList);
                Log.d(FangConstant.Log_Tag,"insertIntoSql--------count:"+count);
                localServices.updateVersionNum(1);
}

这里其实还有点问题,其实应该首先判断sharedpreferences中是否已经存在了已经选择的城市的数据,如果有了,就不需要再跳转到selectcity activity中。

2.SelectCityActivity

selectcityactivity主要有三个自定义View和一个ListView组成。两个自定义View为上方的ActionBar,SearchBar和右侧的SideBar,分别对应的类是ActionBar,SearchBar,ListViewSideBar。

ListVIew中的数据来自于Sqlite

private void init() {

        CityLocalDao localServices = new CityLocalDao(this);
        ArrayList<City> cityList = localServices.queryAllCityList();
        ArrayList<City> hotCityList = localServices.queryHotCityList();
        adapter = new CityListViewAdapter(this,cityList,hotCityList);
        listView.setAdapter(adapter);

        actionBarLeft.setOnClickListener(this);
}

ListViewSideBar中添加了一个接口OnIndexerClickListener,用于添加监听事件

sideBar.setOnIndexerClickListener(new ListViewSideBar.OnIndexerClickListener() {
            @Override
            public void onIndexerClick(int index, String indexStr) {
                int position = adapter.getPositionForSection(indexStr.charAt(0));
                listView.setSelection(position);
            }
 });

ListView 滑动时显示IndexToast,滑动结束后,IndexToast延迟1秒后消失

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            private String cityIndex = "";
            private Handler handler = new Handler();
            private Runnable run = null;
            @Override
            public void onScrollStateChanged(AbsListView absListView, int scrollState) {
                switch (scrollState) {
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                        run = new Runnable() {
                            @Override
                            public void run() {
                                indexToast.setVisibility(View.GONE);
                            }
                        };
                        handler.postDelayed(run,1000);
                        break;
                    case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
                        if(run != null) {
                            handler.removeCallbacks(run);
                        }
                        indexToast.setVisibility(View.VISIBLE);
                        break;
                }
            }

            @Override
            public void onScroll(AbsListView absListView, int i, int i2, int i3) {

                if(indexToast.getVisibility()==View.VISIBLE) {
                    cityIndex = adapter.getCityIndex(i);
                    indexToast.setText(cityIndex);
                }
            }
});

在热门城市中使用的是自定义GridView CustomGridView,因为在ListView 中添加GridView后,GridView的高度没有自适应,需要重新测量GridView的高度

//重新测量GridView的高度
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
     super.onMeasure(widthMeasureSpec, expandSpec);
}

这里只对热门城市的Item添加了Onclick事件,获取当前选择的城市对象,并添加到SharedPreferences

 public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        City city = (City)gridViewAdapter.getItem(i);
        Log.d(FangConstant.Log_Tag,"grid city:"+city.toString());

        SharedPreferences sp = context.getSharedPreferences(FangConstant.PreferenceName, context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(FangConstant.CurrentCityID,city.getId());
        editor.putString(FangConstant.CurrentCityName,city.getName()
        editor.commit();

        Intent intent = new Intent(context, MainActivity.class);
        context.startActivity(intent);
}

3.MainActivity

MainActivity 使用了帧布局,通过最下方的RadioGroup,实现4个Fragment的切换。

public void onCheckedChanged(RadioGroup radioGroup, int i) {
            int position = 0;
            switch (i) {
                case R.id.rb_home: position = 0; break;
                case R.id.rb_poi:  position = 1; break;
                case R.id.rb_user: position = 2; break;
                case R.id.rb_more: position = 3; break;
            }
            Fragment f = mainPageAdapter.getItem(1);
            Log.d(FangConstant.Log_Tag,"OnCheckedChangeListener-----------------f:"+f);
            if(f != null) {
                ((PoiFragment)f).refresh();
            }
            refreshPage(position);
}

首页为 HomeFragment,也是以ListView为主要框架,ListView中共分为4类Item,第一个Item为viewpager,每个Page中是一个GridView,数据都是从DataUtil中获取,第二个Item为TableVIew,最后一个Item是一个简单的描述。中间的Item数据都是在ProListAsyncTask中处理的,首先查看sqlite中是否有数据,如果没有则从服务器中获取,并插入到sqlite中。最后在AsyncTask的onPostExecute中把数据添加到listViewAdapter中,刷新ListVIew。这里的算法逻辑和真正美团中的逻辑肯定是不一样的,大家也可以根据自己的喜好修改。这里面有个细节,从服务器中获取后的数据,在插入到sqlite时,这段代码是放在新起的线程中的。

protected ArrayList<Product> doInBackground(Void... voids) {
           final ProductLocalDao localDao = new ProductLocalDao(getActivity());

           ArrayList<Product> localProList =  localDao.queryAllProductions();
            if(localProList.size()==0) {
                ProductRemoteDao remoteDao = new ProductRemoteDao();
                final ArrayList<Product> proList = remoteDao.queryAllProList();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        localDao.insertIntoProductions(proList);
                    }
                }).start();
                return proList;
            }else {
                return localProList;
            }
}

protected void onPostExecute(ArrayList<Product> proList) {
         Log.d(FangConstant.Log_Tag,"proList-----------------size:"+proList.size());
         listViewAdapter.getList().clear();
         listViewAdapter.getList().addAll(proList);
         listViewAdapter.notifyDataSetChanged();
}

Item中图片的加载,首先是直接从内存中获取,如果不存在,再从cache中查找,如果还没有,则去服务器中获取,得到后再写入cache和内存中。

Bitmap bitmap = ImageLoader.getInstance().getBitmapFromCache(pro.getIcon());
if(bitmap != null) {
       holder.iv.setImageBitmap(bitmap);
}else {
       ImageLoader.getInstance().loadBitmapFromHttp(context,holder.iv, pro.getIcon());
}
FileCache fileCache = new FileCache(context);
Btmap bitmap = fileCache.getFile(fileName);
if(bitmap == null) {
    bitmap = HttpUtil.getHttpConnectionForDownloadImage(url);
}

if(bitmap != null) {
        ImageLoader.instance.addBitmapToCache(fileName,bitmap);

        msgMessage.arg1=1;
        handler.sendMessage(msgMessage);
        //先让线程通知主线程更新UI,再把图片存到本地
        fileCache.saveFile(fileName,bitmap);
}

这里也是只用中间的Item有点击事件

Product pro = (Product)listViewAdapter.getItem(i);
if(pro != null) {
      Intent intent = new Intent(getActivity(), PlaceOrderActivity.class);
      startActivity(intent);
}

PlaceOrderActivity主要使用CustomScrollView布局,主要的知识点是使用ScrollView的onScrollChanged事件,实现订单滑动时的悬浮效果。

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
     super.onScrollChanged(l, t, oldl, oldt);
     if(onScrollListener != null) {
         onScrollListener.OnScroll(t);
     }
}
public void OnScroll(int scrollY) {
         int mBuyLayout2ParentTop = Math.max(scrollY, imageView.getHeight());
         imageView.layout(0,0+scrollY/2,imageView.getWidth(),imageView.getHeight()+scrollY/2);
         topView.layout(0, mBuyLayout2ParentTop, topView.getWidth(), mBuyLayout2ParentTop + topView.getHeight());
}
  1. 主要页面效果

城市选择界面

APP首页

订单界面

商家界面

results matching ""

    No results matching ""